#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "bmock.hpp"
#include "bmock_control_tools_mock.hpp"

struct arg_tester2 {
	arg_tester2() {
		BMOCK_CREATE_MOCK(*);
	}
};

static void g() {
	MOCK_VOID(0,());
}
static void h(int x, int& y) {
	MOCK_VOID(2,(IN(x),OUT(y)));
}
static int f(int x, int& y) {
	MOCK(2,(IN(x),OUT(y)));
	return 1;
}

BMOCK_TEST(arg_tester2,test_void_stub_no_arguments_no_other_expectation)
{
	BMOCK_STUB(g());
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(g());
	BMOCK_VERIFY;
}

BMOCK_TEST(arg_tester2,test_void_stub_with_arguments_no_other_expectation)
{
	int x=4;
	int y=8;
	int z=0;

	BMOCK_STUB(h(2,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(h(x,z));
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z);
}

BMOCK_TEST(arg_tester2,test_not_void_stub_with_arguments_no_other_expectation)
{
	int x=4;
	int y=8;
	int z=0;
	int r=0;

	BMOCK_STUB_RETURN(10,f(2,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(r=f(x,z));
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z);
	BOOST_CHECK_EQUAL(r,10);
}

struct test_exception2 : public std::exception {

};

BMOCK_TEST(arg_tester2,test_void_stub_expect_throw_no_other_expectation)
{
	BMOCK_STUB_THROW(new test_exception2(),g());
	BMOCK_REPLAY;
	BOOST_CHECK_THROW(g(),test_exception2);
	BMOCK_VERIFY;
}

BMOCK_TEST(arg_tester2,test_void_stub_no_arguments_with_other_expectation_multiple_calls_to_stub)
{
	int x=4;
	int y=8;
	int z_1=0;
	int z_2=0;
	int r;
	BMOCK_EXPECT_RETURN(10,f(x,y));
	BMOCK_STUB(g());
	BMOCK_EXPECT(h(x,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(g());
	BOOST_CHECK_NO_THROW(r=f(x,z_1));
	BOOST_CHECK_NO_THROW(g());
	BOOST_CHECK_NO_THROW(h(x,z_2));
	BOOST_CHECK_NO_THROW(g());
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z_1);
	BOOST_CHECK_EQUAL(y,z_2);
	BOOST_CHECK_EQUAL(r, 10);
}

BMOCK_TEST(arg_tester2,test_void_stub_no_arguments_with_other_expectation_no_calls_to_stub)
{
	int x=4;
	int y=8;
	int z_1=0;
	int z_2=0;
	int r;
	BMOCK_EXPECT_RETURN(10,f(x,y));
	BMOCK_STUB(g());
	BMOCK_EXPECT(h(x,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(r=f(x,z_1));
	BOOST_CHECK_NO_THROW(h(x,z_2));
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z_1);
	BOOST_CHECK_EQUAL(y,z_2);
	BOOST_CHECK_EQUAL(r, 10);
}

BMOCK_TEST(arg_tester2,test_void_stub_with_arguments_with_other_expectation_multiple_calls_to_stub_expectation_overwrites_stub)
{
	int x=4;
	int y=8;
	int x_1=3;
	int y_1=9;
	int z_1=0;
	int z_2=0;
	int l_1=0;
	int l_2=0;
	int l_3=0;
	int r;
	BMOCK_EXPECT_RETURN(10,f(x,y));
	BMOCK_STUB(h(x_1,y_1));
	BMOCK_EXPECT(h(x,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(h(x,l_1));
	BOOST_CHECK_NO_THROW(r=f(x,z_1));
	BOOST_CHECK_NO_THROW(h(x,z_2));
	BOOST_CHECK_NO_THROW(h(x,l_2));
	BOOST_CHECK_NO_THROW(h(y,l_3));
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z_1);
	BOOST_CHECK_EQUAL(y,z_2);
	BOOST_CHECK_EQUAL(y_1,l_1);
	BOOST_CHECK_EQUAL(y_1,l_2);
	BOOST_CHECK_EQUAL(y_1,l_3);
	BOOST_CHECK_EQUAL(r, 10);
}

BMOCK_TEST(arg_tester2,test_multiple_stubs_and_expectations_multiple_calls_to_stubs_expectations_over_write)
{
	int x=4;
	int y=8;
	int x_1=3;
	int y_1=9;
	int z_1=0;
	int z_2=0;
	int l_1=0;
	int l_2=0;
	int l_3=0;
	int r;
	BMOCK_STUB(g());
	BMOCK_EXPECT_RETURN(10,f(x,y));
	BMOCK_STUB(h(x_1,y_1));
	BMOCK_EXPECT(h(x,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(g());
	BOOST_CHECK_NO_THROW(h(x_1,l_1));
	BOOST_CHECK_NO_THROW(r=f(x,z_1));
	BOOST_CHECK_NO_THROW(g());
	BOOST_CHECK_NO_THROW(h(x,z_2));
	BOOST_CHECK_NO_THROW(h(x,l_2));
	BOOST_CHECK_NO_THROW(h(x_1,l_3));
	BOOST_CHECK_NO_THROW(g());
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z_1);
	BOOST_CHECK_EQUAL(y,z_2);
	BOOST_CHECK_EQUAL(y_1,l_1);
	BOOST_CHECK_EQUAL(y_1,l_2);
	BOOST_CHECK_EQUAL(y_1,l_3);
	BOOST_CHECK_EQUAL(r, 10);
}

BMOCK_TEST(arg_tester2,test_multiple_stubs_and_expectations_no_calls_to_stub)
{
	int x=4;
	int y=8;
	int x_1=3;
	int y_1=9;
	int z_1=0;
	int z_2=0;
	int r;
	BMOCK_STUB(g());
	BMOCK_EXPECT_RETURN(10,f(x,y));
	BMOCK_STUB(h(x_1,y_1));
	BMOCK_EXPECT(h(x,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(r=f(x,z_1));
	BOOST_CHECK_NO_THROW(h(x,z_2));
	BMOCK_VERIFY;
	BOOST_CHECK_EQUAL(y,z_1);
	BOOST_CHECK_EQUAL(y,z_2);
	BOOST_CHECK_EQUAL(r, 10);
}

BOOST_AUTO_TEST_CASE(test_unexpected_STUB2) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+7);

	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->error(bmock::message(bmock::INVALID_STUB),loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t);
		__BMOCK_REPLAY_C(c1);
		BOOST_CHECK_THROW(__BMOCK_STUB_C(c1,g()),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
}

BOOST_AUTO_TEST_CASE(test_multiple_STUB_for_the_same_function2) {
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+8);

	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->error(bmock::message(bmock::INVALID_STUB_SAME_FUNC),loc));
	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->abort(loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t);__BMOCK_CREATE_MOCK_C((&c1),*);
		BOOST_CHECK_NO_THROW(__BMOCK_STUB_C(c1,g()));
		BOOST_CHECK_THROW(__BMOCK_STUB_C(c1,g()),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
}

BOOST_AUTO_TEST_CASE(test_expectation_overwrites_stub2)
{
	int x=9;
	int y=0;
	int z=0;
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+7);

	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->check_equal("9","0",bmock::message(bmock::ARG_VALUE,"x"),loc));
	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->abort(loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t); __BMOCK_CREATE_MOCK_C((&c1),*);
		__BMOCK_EXPECT_C(c1,h(x,y));
		__BMOCK_STUB_C(c1,h(x,y));
		__BMOCK_REPLAY_C(c1);
		BOOST_CHECK_THROW(h(z,y),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
}

BOOST_AUTO_TEST_CASE(test_non_strict_expectation_overwrites_stub2)
{
	int x=9;
	int y=0;
	int z=0;
	__BMOCK_CONTROL(c);
	const bmock::control_tools_ptr t(new bmock::control_tools_mock(c));
	const bmock::location          loc(__FILE__,__LINE__+8);

	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->check_equal("9","0",bmock::message(bmock::ARG_VALUE,"x"),loc));
	__BMOCK_EXPECT_THROW_C(c,new bmock::location(loc),t->abort(loc));
	__BMOCK_REPLAY_C(c);
	{
		bmock::test_mode_control c1(bmock::location(__FILE__,__LINE__),t);__BMOCK_CREATE_MOCK_C((&c1),*);
		__BMOCK_NON_STRICT_C(c1) {
			__BMOCK_EXPECT_C(c1,h(x,y));
			__BMOCK_STUB_C(c1,h(x,y));
		}
		__BMOCK_REPLAY_C(c1);
		BOOST_CHECK_THROW(h(z,y),bmock::location);
	}
	__BMOCK_VERIFY_C(c);
}

BMOCK_TEST(arg_tester2, test_mocked_area_becomes_empty_check_if_stub) {
	int y = 0;

	BMOCK_EXPECT(g());
	BMOCK_REPEAT_RANGE(1,3);
	BMOCK_STUB(h(y,y));
	BMOCK_REPLAY;
	BOOST_CHECK_NO_THROW(g());
	BOOST_CHECK_NO_THROW(h(y,y));
	BMOCK_VERIFY;
}
